//
import patchVnode from "./patchVnode";
import createElement from "./createElement";

function checkSameVnode(a, b) {
    return a.sel == b.sel && a.key == b.key
}

export default function updateChildren(parentElm,oldCh,newCh){
    // 新前
    let newStartIdx = 0
    let newStartVnode = newCh[newStartIdx]
    // 旧前
    let oldStartIdx = 0
    let oldStartVnode = oldCh[oldStartIdx]
    // 新后
    let newEndIdx = newCh.length - 1
    let newEndVnode = newCh[newEndIdx]
    // 旧后
    let oldEndIdx = oldCh.length - 1
    let oldEndVnode = oldCh[oldEndIdx]

    let keyMap = new Map();
    while (oldStartIdx<=oldEndIdx && newStartIdx<=newEndIdx){
        if(oldStartVnode == null){
            oldStartVnode = oldCh[++oldStartIdx]
        }else if(oldEndVnode == null){
            oldEndVnode = oldCh[--oldEndIdx]
        }else if(newStartVnode == null){
            newStartVnode = newCh[++newStartIdx]
        }else if(newEndVnode == null){
            newEndVnode = newCh[--newEndIdx]
        }else if(checkSameVnode(newStartVnode, oldStartVnode)){
            // 新前与旧前
            patchVnode(oldStartVnode,newStartVnode)
            newStartVnode = newCh[++newStartIdx]
            oldStartVnode = oldCh[++oldStartIdx]
        }else if(checkSameVnode(newEndVnode,oldEndVnode)){
            // 新后与旧后
            patchVnode(oldEndVnode,newEndVnode)
            newEndVnode = newCh[--newEndIdx]
            oldEndVnode = oldCh[--oldEndIdx]
        }else if(checkSameVnode(newEndVnode,oldStartVnode)){
            // 新后与旧前
            // 更新节点内容
            patchVnode(oldStartVnode,newEndVnode)
            // 把新后插入到旧后的后面
            // parentElm.insertBefore(newEndVnode.elm,oldEndVnode.elm.nextSibling) // 报错？？？？新前与旧后相等时，不是新前移动到旧后之后吗？
            parentElm.insertBefore(oldStartVnode.elm,oldEndVnode.elm.nextSibling)
            newEndVnode = newCh[--newEndIdx]
            oldStartVnode = oldCh[++oldStartIdx]
        }else if(checkSameVnode(newStartVnode,oldEndVnode)){
            // 新前与旧后
            patchVnode(oldEndVnode,newStartVnode)
            parentElm.insertBefore(newStartVnode.elm,oldStartVnode.elm)
            newStartVnode = newCh[++newStartIdx]
            oldEndVnode = oldCh[--oldEndIdx]
        }else{
            // 四种情况都没命中时
            if(!keyMap.size){
                for(let i = oldStartIdx;i<=oldEndIdx;i++){
                    const key = oldCh[i].key
                    if(key!=undefined){
                        keyMap.set(key ,i)
                    }

                }
            }
            console.log(keyMap)
            // 寻找当前项在在keyMap中的映射的位置
            const idxInOld = keyMap.get(newStartVnode.key)
            if(idxInOld === undefined){
                // 如果idxInOld是undefined，那说明这是全新项，插入到老节点的oldStatIdx前
                // 新加入的项还不是真正的dom节点，是虚拟dom
                parentElm.insertBefore(createElement(newStartVnode),oldStartVnode.elm)

            }else{
                // 如果idxInOld不为undefined时，说明在旧节点中存在，需要移动
                const elmToMove = oldCh[idxInOld]
                patchVnode(elmToMove,newStartVnode)
                oldCh[idxInOld] = null
                parentElm.insertBefore(elmToMove.elm,oldStartVnode.elm)
            }
            // 此时只移动新的节点
            newStartVnode = [newStartIdx++]
        }
    }
    if(newStartIdx<newEndIdx){
        const before = newCh[newStartIdx+1]==null?null:newCh[newStartIdx+1].elm
        for(let i = newStartIdx;i<=newEndIdx;i++){
            // insertBefore 方法可以自动识别null，如果是null就会自动排到队尾去，和appendChild一致
            // ？？？？为什么这里需要创建节点createElement(newCh[i])，而不能直接取newCh[i]
            parentElm.insertBefore(createElement(newCh[i]),oldCh[oldStartIdx].elm)
        }
    }else if(oldStartIdx<oldEndIdx){
        for(let i = oldStartIdx;i<=oldEndIdx;i++){
            if(oldCh[i]){
                parentElm.removeChild(oldCh[i].elm)
            }
        }
    }
}
